/* 
* Copyright (C) 2005, 2006 Liu Di <liudidi@gmail.com> 
*
* Copyright (C) 2007 Wei Lian <lianwei3@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "sopfork.h"
#include "record.h"
#include "header.h"
#include "config.h"
#include "channel.h"
#include "timing.h"
#include "tabwidget.h"
#include "mainwindow.h"
#include "menubar.h"
#include "utils.h"
#include "mystatusbar.h"


Record::Record (QWidget * parent, const char *name):
MyHBox (parent, name),
tabwidget (static_cast < TabWidget * >(parent))
{
    ///set page type 
    pagetype = "record";

    recordfp = new QFile ();
    snrecord = 0;

    launchtimer = new QTimer (this);
    connect (launchtimer, SIGNAL (timeout ()), this, SLOT (launchRecord ()));

    quittimer = new QTimer (this);
    connect (quittimer, SIGNAL (timeout ()), this, SLOT (quitRecord ()));

    ///row
    ///status bar
    statusbar = new QStatusBar (this);
    statusbar->setSizeGripEnabled (false);
    statusbar->hide ();
    ///input for timing
    timing = new Timing (this);
    ///button record
    buttonrecord = new QToolButton (this);
    buttonrecord->setTextLabel (tr ("Record"));
    buttonrecord->setAutoRaise (true);
    buttonrecord->setUsesTextLabel (true);
    buttonrecord->setToggleButton (TRUE);
//    buttonrecord->setMaximumSize(buttonrecord->sizeHint());
    //signal
    connect (buttonrecord, SIGNAL (toggled (bool)), this, SLOT (onButtonRecordToggled (bool)));
    ///button delete
    QToolButton *but = new QToolButton (this);
    but->setTextLabel (tr ("x"));
    but->setAutoRaise (true);
    but->setUsesTextLabel (true);
    but->setMaximumSize (but->sizeHint ());
    connect (but, SIGNAL (clicked ()), this, SLOT (removeTab ()));

    ///initialize flagMenu
    flagMenu = false;
}

Record::~Record ()
{
    tabwidget->detachSop (&sopfork, this);
    ///
    if (snrecord) {
	recordfp->close ();
	::close (snrecord->socket ());
	delete snrecord;
	snrecord = 0;
    }
    delete recordfp;
}


void
Record::streamReady (int fd)
{
    int ret;
    char buff[1024];
    ret =::read (fd, buff, sizeof (buff));
    if (ret <= 0) {
	if (ret < 0)
	    perror ("record socketnotifier");

	recordfp->close ();
	::close (fd);
	delete snrecord;
	snrecord = 0;
	buttonrecord->setPaletteForegroundColor (Qt::black);

	/////restart record
	launchtimer->start (2000, true);

	return;
    }
    ::write (recordfp->handle (), buff, ret);
}


void
Record::launchRecord ()
{
    ///show message on statusbar
    static_cast < MainWindow * >(qApp->mainWidget ())
	->statusbar->showMessage (tr ("Connecting..."));
    ////launch Sop
    if (!sopfork) {
	if (tabwidget->attachSop (&sopfork, this, channelurl, channelname) == TRUE) {
	} else
	    fprintf (stderr, "failed to launch sp-sc!\n");
    } else if (sopfork->channelurl != channelurl) {
	tabwidget->detachSop (&sopfork, this);
	if (tabwidget->attachSop (&sopfork, this, channelurl, channelname) == TRUE) {
	} else
	    fprintf (stderr, "failed to launch sp-sc!\n");
    }
    ////handle stream
    int sockfd = connect_to_server ("127.0.0.1",
				    atoi (sopfork->outport));
    if (sockfd < 0) {
	///restart
	launchtimer->start (2000, true);
	return;
    }
    ::write (sockfd, "1",::strlen ("1") + 1);
    ///parse header
    char buf[19];
    if (::recv (sockfd, buf, sizeof (buf), 0) != sizeof (buf)) {
	fprintf (stderr, "err while parsing head\n");
	::close (sockfd);
	buttonrecord->setOn (false);
	return;
    }
    ///testing data availibility
    int nread;
    ::ioctl (sockfd, FIONREAD, &nread);
    if (nread <= 0) {
	::close (sockfd);
	////
	if (nread < 0)
	    perror ("ioctl get nread of socket");
	///restart
	launchtimer->start (2000, true);
	return;
    }
    ////data availible
    QString data_path = static_cast < MainWindow * >(qApp->mainWidget ())
	->vboxconfig->editrecorddir->text ();
    QDir dir (data_path);
    if (!dir.exists ())
	if (!dir.mkdir (data_path)) {
	    perror ("failed to create record path");
	    ::close (sockfd);
	    buttonrecord->setOn (false);
	    return;
	}
    data_path += sopfork->channelname.replace (QRegExp ("\\/+"), "#");	///eliminate harmful character
    data_path += QDateTime::currentDateTime ().toString ();
    data_path += ".asf";
    recordfp->setName (data_path);
    if (!recordfp->open (IO_WriteOnly)) {
	perror ("record file name is invalid");
	::close (sockfd);
	buttonrecord->setOn (false);
	return;
    }
    if (snrecord) {
	fprintf (stderr, "QSocketNotifier exist!\n");
	return;
    }
    snrecord = new QSocketNotifier (sockfd, QSocketNotifier::Read, this);
    connect (snrecord, SIGNAL (activated (int)), SLOT (streamReady (int)));
    buttonrecord->setPaletteForegroundColor (Qt::red);
}

void
Record::quitRecord ()
{
    buttonrecord->setOn (false);
}

void
Record::onButtonRecordToggled (bool t)
{
    if (t) {
	///if not launched from bookmark or history
	if (!flagMenu) {
	    channelurl = static_cast < MainWindow * >(qApp->mainWidget ())
		->editsearch->text ();
	    ///editsearch has focus and is a valid Sop URL
	    if (static_cast < MainWindow * >(qApp->mainWidget ())
		->editsearch->hasFocus () && static_cast < MainWindow * >(qApp->mainWidget ())
		->channel->SopMatch (channelurl, channelname, channeltype)) {
	    } else {
		///editsearch has no focus
		QListViewItem *item = static_cast < MainWindow * >(qApp->mainWidget ())
		    ->channel->currentItem ();
		if (!item || item->depth () != 1) {
		    buttonrecord->setOn (false);
		    return;
		}
		///get channel name and url
		channelname = item->text (NAME_COLUMN);
		channelurl = item->text (URL_COLUMN);
		channeltype = item->text (STREAM_COLUMN);
	    }
	}
	///get time for current, from and to
	int current =
	    QTime::currentTime ().hour () * 60 * 60 +
	    QTime::currentTime ().minute () * 60 + QTime::currentTime ().second ();
	int from =
	    timing->fromHour->text ().toInt () * 60 * 60 +
	    timing->fromMinute->text ().toInt () * 60;
	int to =
	    timing->toHour->text ().toInt () * 60 * 60 + timing->toMinute->text ().toInt () * 60;
	///calculate delay time for record start and stop
	int delaystart, delaystop;
	QString fromdaytime, todaytime;
	if (timing->fromHour->text ().isEmpty ()
	    && timing->toHour->text ().isEmpty ()) {
	    delaystart = 0;
	    delaystop = -1;
	    ///
	    fromdaytime = tr ("today/now");
	    todaytime = tr ("inf");
	} else if (timing->fromHour->text ().isEmpty ()) {
	    delaystart = 0;
	    delaystop = to - current >= 0 ? to - current : to - current + 24 * 60 * 60;
	    ///
	    fromdaytime = tr ("today/now");
	    todaytime = to - current >= 0 ? tr ("today/") : tr ("tomor/");
	    todaytime += timing->toHour->text () + ":" + timing->toMinute->text ();
	    ///
	} else if (timing->toHour->text ().isEmpty ()) {
	    delaystart = from - current >= 0 ? from - current : from - current + 24 * 60 * 60;
	    delaystop = -1;
	    ///
	    fromdaytime = from - current >= 0 ? tr ("today/") : tr ("tomor/");
	    fromdaytime += timing->fromHour->text () + ":" + timing->fromMinute->text ();
	    todaytime = tr ("inf");
	    ///
	} else {
	    delaystart = from - current >= 0 ? from - current : from - current + 24 * 60 * 60;
	    delaystop = to - from >= 0 ? to - from : to - from + 24 * 60 * 60;
	    delaystop = delaystop + delaystart;
	    ///
	    fromdaytime = from - current >= 0 ? tr ("today/") : tr ("tomor/");
	    fromdaytime += timing->fromHour->text () + ":" + timing->fromMinute->text ();
	    switch ((from - current < 0) + (to - from < 0)) {
	    case 0:
		todaytime = tr ("today/");
		break;
	    case 1:
		todaytime = tr ("tomor/");
		break;
	    case 2:
		todaytime = tr ("aftto/");
	    }
	    todaytime += timing->toHour->text () + ":" + timing->toMinute->text ();
	}
	///start timer for starting record
	launchtimer->start (delaystart * 1000, true);
	///start timer for stoping record
	if (delaystop >= 0) {
	    quittimer->start (delaystop * 1000, true);
	}
	///change interface
	statusbar->message (fromdaytime + "-" + todaytime + "|" + channelname);
	statusbar->show ();
	timing->hide ();
	///log
	printf ("record start after %d hour and %d minute %d second\n",
		delaystart / 3600, delaystart / 60 % 60, delaystart % 60);
	if (delaystop >= 0)
	    printf ("   and stop after %d hour and %d minute %d second\n",
		    delaystop / 3600, delaystop / 60 % 60, delaystop % 60);
	///assign channel name to tab label
	tabwidget->setTabLabel (this, reduceLabelLength (channelname));
	///add to history
	static_cast < MainWindow * >(qApp->mainWidget ())
	    ->menubar->addToPopupMenu (static_cast < MainWindow * >
				       (qApp->mainWidget ())->
				       menubar->history, channelurl, channelname, channeltype);
    } else			///function setOn(false) will trigger the following code
    {
	///close file, socket and socketnotifier
	if (snrecord) {
	    recordfp->close ();
	    ::close (snrecord->socket ());
	    delete snrecord;
	    snrecord = 0;
	}
	///reset button color
	buttonrecord->setPaletteForegroundColor (Qt::black);
	///stop timer
	launchtimer->stop ();
	quittimer->stop ();
	///change interface
	statusbar->hide ();
	timing->show ();
	///kill sop
	tabwidget->detachSop (&sopfork, this);
	///assign channel name to tab label
	tabwidget->setTabLabel (this, tr ("record"));
	///clean statusbar
	static_cast < MainWindow * >(qApp->mainWidget ())
	    ->statusbar->showMessage ("");
    }

}

void
Record::removeTab ()
{
    if (tabwidget->count () == 1)
	return;
    tabwidget->removePage (this);
    delete this;
}
